bitkeeper revision 1.456 (3f6de470w7_JGb139gaotteaX7UDcQ)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Sun, 21 Sep 2003 17:48:32 +0000 (17:48 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Sun, 21 Sep 2003 17:48:32 +0000 (17:48 +0000)
xen_serial.c, kernel.c:
  Robustify Xen's serial handling. We now assert DTR and RTS so that we play nicely with flow control. Also the rx interrupt reads all chars from the fifo rather than just one. TODO: tx should be interrupt driven, and domains shouldn't be echo to serial but should go to DOM0 only.

xen/common/kernel.c
xen/drivers/char/xen_serial.c

index d1cbe51863cc50e8f906019beee75be8ab2c251c..7b384a90ca41fa434a275df03a4f5d269d956809 100644 (file)
@@ -218,8 +218,6 @@ void cmain (unsigned long magic, multiboot_info_t *mbi)
 }
 
 
-#ifdef CONFIG_OUTPUT_SERIAL
-
 #define SERIAL_BASE 0x3f8
 #define RX_BUF      0
 #define TX_HOLD     0
@@ -239,24 +237,24 @@ void init_serial(void)
     outb(115200/opt_ser_baud, SERIAL_BASE+DIVISOR_LO);
     outb(0, SERIAL_BASE+DIVISOR_HI);
     outb(0x03, SERIAL_BASE+DATA_FORMAT);
+    
+    /* DTR and RTS should both be high, to keep other end happy. */
+    outb(0x02, SERIAL_BASE+LINE_CTL);
 
     /* No interrupts. */
     outb(0x00, SERIAL_BASE+INT_ENABLE);
 }
 
 
+#ifdef CONFIG_OUTPUT_SERIAL
 void putchar_serial(unsigned char c)
 {
     if ( c == '\n' ) putchar_serial('\r');
     while ( !(inb(SERIAL_BASE+LINE_STATUS)&(1<<5)) ) barrier();
     outb(c, SERIAL_BASE+TX_HOLD);
 }
-
 #else
-
-void init_serial(void) {}
 void putchar_serial(unsigned char c) {}
-
 #endif
 
 
index 95107e587d5421e2d726bdc8309714903f54f30f..7a1560ca5b2cbdca6505a6661688d5992df77890 100644 (file)
@@ -56,15 +56,16 @@ static void serial_rx_int(int irq, void *dev_id, struct pt_regs *regs)
     u_char c; 
     key_handler *handler; 
 
-    /* clear the interrupt by reading the character */
-    c = inb(SERIAL_BASE + NS16550_RBR);
+    while ( (inb(SERIAL_BASE + NS16550_LSR) & 1) == 1 )
+    {
+        c = inb(SERIAL_BASE + NS16550_RBR);
 
-    /* if there's a handler, call it: we trust it won't screw us too badly */
-    if((handler = get_key_handler(c)) != NULL) 
-       (*handler)(c, dev_id, regs); 
+        if( (handler = get_key_handler(c)) != NULL ) 
+            (*handler)(c, dev_id, regs); 
 
-    if(serial_echo) 
-       printk("%c", c); 
+        if ( serial_echo ) 
+            printk("%c", c);
+    } 
 }
 
 void initialize_serial() 
@@ -74,16 +75,17 @@ void initialize_serial()
     /* setup key handler */
     add_key_handler('~', toggle_echo, "toggle serial echo");
     
-    /* Should detect this, but must be a ns16550a at least, surely? */
-    fifo = 1;  
-    if(fifo) {
-       /* Clear FIFOs, enable, trigger at 1 byte */
-       outb(NS16550_FCR_TRG1 | NS16550_FCR_ENABLE |
-            NS16550_FCR_CLRX  | NS16550_FCR_CLTX, SERIAL_BASE+NS16550_FCR);
-    }
+    /* This assumes we have a 16550. It's pretty darned likely really! */
+    /* Clear FIFOs, enable, trigger at 1 byte */
+    outb(NS16550_FCR_TRG1 | NS16550_FCR_ENABLE |
+         NS16550_FCR_CLRX  | NS16550_FCR_CLTX, 
+         SERIAL_BASE+NS16550_FCR);
 
-    outb(NS16550_MCR_OUT2, SERIAL_BASE + NS16550_MCR);   /* Modem control */
-    outb(NS16550_IER_ERDAI, SERIAL_BASE + NS16550_IER ); /* Setup interrupts */
+    /* Enable receive interrupts. Also remember to keep DTR/RTS asserted. */
+    outb(NS16550_MCR_OUT2|NS16550_MCR_DTR|NS16550_MCR_RTS, 
+         SERIAL_BASE + NS16550_MCR);
+    outb(NS16550_IER_ERDAI, 
+         SERIAL_BASE + NS16550_IER );
 
     if((rc = request_irq(4, serial_rx_int, SA_NOPROFILE, "serial", 0)))
        printk("initialize_serial: failed to get IRQ4, rc=%d\n", rc);